home *** CD-ROM | disk | FTP | other *** search
/ Aminet 52 / Aminet 52 (2002)(GTI - Schatztruhe)[!][Dec 2002].iso / Aminet / misc / emu / Apex-src.lha / AMIGAHAN.68K < prev    next >
Text File  |  2001-09-30  |  44KB  |  1,273 lines

  1. ;AMIGAHAN.68K    AUG-06-90    (also see INFOSTR)
  2. ;Console handler for the Amiga
  3. ;Written by Loren Blaney
  4. ;This is based on QUMEHANA.68K
  5. ;
  6. ;Revision history:
  7. ;APR-10-87, Original.
  8. ;JUN-88, Changed dimensions to 640x240, added installable fonts,
  9. ; setable colors, faster scrolls, characters that can be positioned
  10. ; anywhere (not just on character cell boundaries), CHKUSR, fixed CAPS
  11. ; LOCK problem, and auto-repeat.
  12. ;JUL-06-88, Fixed DIV bug (dividend is 32 bits).
  13. ;AUG-06-90, Added address of font table to GETINFO array.
  14. ;
  15. ;Notes:
  16. ;Beware of stack space near end. If this program is made a few bytes
  17. ; bigger, the stack will eat it.
  18. ;Also, there is an interrupt other than level 2 that occurs at boot up.
  19. ;
  20. ;This handler differs from the Apple handler in that a <CR> does not
  21. ; erase the rest of the line, tabs are not deleted correctly when using
  22. ; the "<--" key. Null characters are not suppressed. This handler does
  23. ; not the have the <ESC> cursor commands of the Apple, but it does have
  24. ; a cleaner line delete (CTRL-X) and it has an undelete command (CTRL-Z)
  25.  
  26. ;Locations in INTA.68K:
  27. ;WARNING: these routines may clobber D0 and A6
  28. CLEAR    EQU    $8F0        ;40 clear the current bit map
  29. BITMAP    EQU    $A88        ;108 BITMAP(ADDR, WIDTH, HEIGHT, DEPTH)
  30. BITMAP2    EQU    $A8E        ;109 BITMAP2(MAGX, Y, OFFX, Y, INVX, Y)
  31. VIEW    EQU    $A94        ;110, VIEW(ADDR,BPLCON0)
  32.  
  33. RASTER    EQU    $B5A        ;Location of current bit map
  34. WIDTH    EQU    $B5E        ;Dimensions of RASTER in pixels
  35. HEIGHT    EQU    $B62
  36. DEPTH    EQU    $B66
  37. MAGX    EQU    $B6A        ;Parameters affecting how coordinates
  38. MAGY    EQU    $B6E        ; are remapped from specified to
  39. OFFSETX    EQU    $B72        ; actual hardware values
  40. OFFSETY    EQU    $B76
  41. INVERTX    EQU    $B7A
  42. INVERTY    EQU    $B7E
  43. X0    EQU    $B82        ;Graphics coordinates (these might have
  44. Y0    EQU    $B86        ; been remapped by the above parameters)
  45. X1    EQU    $B8A
  46. Y1    EQU    $B8E
  47. COLOR    EQU    $B92        ;Only lowest byte specifies color reg.
  48. MODES    EQU    COLOR+2        ;Bit 0: complement
  49.                 ;Bit 1: fast (i.e. don't clear zeros)
  50. TEXTURE    EQU    COLOR        ;For dotted lines, etc. Ones indicate
  51.                 ; where points are NOT plotted. 16 bits.
  52.  
  53.     NOLIST
  54.     INCLUDE    SYSPAG        ;Get the system definitions
  55.     LIST
  56.  
  57.     ORG    $7F240        ;*** DEBUG ***
  58. START    EQU    @        ;Address where this handler starts
  59.  
  60. ;======================================================================
  61. ;Buffered console handler (device #0)
  62. ;
  63. CONHAN0    DC.L    OPENI0        ;0 = OPENI
  64.     DC.L    OPENO0        ;1 = OPENO
  65.     DC.L    CHIN0        ;2 = CHIN
  66.     DC.L    CHOUT0        ;3 = CHOUT
  67.     DC.L    CLOSE0        ;4 = CLOSE
  68.     DC.L    GETINFO        ;5 = Get info
  69.     DC.L    DUMMY        ;6 = Spare
  70.     DC.L    CURSOR1        ;7 = Position cursor
  71.     DC.L    DUMMY        ;8
  72.     DC.L    DUMMY        ;9
  73.     DC.L    DUMMY        ;10
  74.     DC.L    SHOCUR        ;11 = Turns the cursor on/off
  75.     DC.L    BUTES        ;12 = Set display attributes
  76.  
  77. ;----------------------------------------------------------------------
  78. ;Open (initialize) the buffered keyboard for input.
  79. ; This will discard any characters in the buffer and any pending
  80. ;  characters from the keyboard (type-ahead buffer).
  81. ;
  82. OPENI0    MOVE.L    #LINBUF,LINPTRF    ;Reset line buffer fill & empty pointers
  83.     MOVE.L    #LINBUF,LINPTRE
  84.     BRA    OPENI1        ;(PBRA) Also open unbuffered keyboard
  85.  
  86. ;----------------------------------------------------------------------
  87. ;Open (initialize) buffered terminal for output
  88. ;
  89. OPENO0    BSR    OPENO        ;Initialize low-level output routines
  90.     BRA    CRLF1        ;(PBRA)
  91.  
  92. ;----------------------------------------------------------------------
  93. ;Get a character from the buffered keyboard and return it in D0.
  94. ;The buffered keyboard handles the following control characters:
  95. ; <-- (CTRL-H):    Delete back one character
  96. ; --> (CTRL-U): Move cursor forward one character
  97. ; DEL:        Delete back one character (same as CTRL-H)
  98. ; CTRL-X:    Delete the entire line
  99. ; CTRL-Z:    Undelete the line
  100. ; WARNING: the "<--" and "DEL" keys will not handle tabs correctly.
  101. ;
  102. CHIN0    MOVEM.L    A0/A1,-(SP)    ;Save registers
  103.     MOVEA.L    LINPTRF,A0    ;Get the line buffer pointers
  104.     MOVEA.L    LINPTRE,A1
  105.  
  106.     CMPA.L    A0,A1        ;Does fill pointer = empty pointer?
  107.     BNE.S    CHIN010        ;Branch if not
  108.     BSR.S    FILLBUF        ;Get a line of characters from keyboard
  109. CHIN010    MOVEQ    #0,D0
  110.     MOVE.B    (A1)+,D0    ;Get character at empty pointer
  111.  
  112.     MOVE.L    A0,LINPTRF    ;Save the pointers
  113.     MOVE.L    A1,LINPTRE
  114.     MOVEM.L    (SP)+,A0/A1    ;Restore registers
  115.     RTS
  116.  
  117. ;----------------------------------------------------------------------
  118. ;Get a line of characters from the keyboard and put them into LINBUF.
  119. ; Registers D0, A0, and A1 are destroyed.
  120. ;
  121. FILLBUF    LEA    LINBUF,A0    ;Reset the pointers to the start of
  122.     MOVEA.L    A0,A1        ; the line buffer
  123.  
  124. FB00    BSR    GETKEYX        ;Get character from keyboard
  125.                 ; (check CTRL-C, etc.)
  126.     CMPI.B    #DEL,D0        ;Is it a delete character?
  127.     BEQ.S    FB05        ;Branch if it is
  128.     CMPI.B    #BS,D0        ;Is it a backspace (back arrow)?
  129.     BNE.S    FB10        ;Branch if not
  130. FB05    CMPA.L    #LINBUF,A0    ;Is it the beginning of the buffer?
  131.     BEQ.S    FB00        ;Branch if so (don't delete anything)
  132.     SUBQ.L    #1,A0        ;Back up 1 character in the line buffer
  133.     MOVEQ    #BS,D0        ;Delete the character on the screen
  134.     BSR    CHOUT1        ;Back up
  135.     MOVEQ    #SPACE,D0    ;Space it out
  136.     BSR    CHOUT1
  137.     MOVEQ    #BS,D0        ;Back up
  138.     BSR    CHOUT1
  139.     BRA    FB00        ;Go get next keystroke
  140.  
  141. FB10    CMPI.B    #FWDSP,D0    ;Forward (right) arrow?
  142.     BNE.S    FB20        ;Branch if not
  143.     CMPI.B    #CR,(A0)    ;Is it at the end of the input line?
  144.     BEQ.S    FB00        ;Branch if it is (ignore it)
  145.     CMPA.L    #LINBUFE,A0    ;Is it beyond the end of the buffer?
  146.     BHS.S    FB00        ;Branch if it is (ignore it)
  147.     MOVE.B    (A0)+,D0    ;Echo char to move forward on screen
  148.     BSR    CHOUT1
  149.     BRA.S    FB00        ;Go get next keystroke
  150.  
  151. FB20    CMPI.B    #'X'-CTRL,D0    ;CTRL-X (line delete)?
  152.     BNE.S    FB30        ;Branch if not
  153.     BSR    DELLINE        ;Delete the line
  154.     BRA.S    FB00
  155.  
  156. FB30    CMPI.B    #'Z'-CTRL,D0    ;CTRL-Z (regurge previous line buffer)?
  157.     BNE.S    FB50        ;Branch if not
  158.     BSR    DELLINE        ;Delete anything on the line & reset A0
  159. FB35    MOVE.B    (A0),D0        ;Get character from previous buffer
  160.     CMPI.B    #CR,D0        ;Is it a carriage return?
  161.     BEQ.S    FB00        ;Branch if yes, we're done
  162.     BSR    CHOUT1        ;Echo this character
  163.     CMPA.L    #LINBUFE,A0    ;Are we beyond the end of the buffer?
  164.     BHS.S    FB00        ;Branch if yes, we're done
  165.     ADDQ.L    #1,A0        ;Increment fill pointer
  166.     BRA.S    FB35        ;Loop until done
  167.  
  168. ;The last character in the line buffer may be a <CR> but anything else
  169. ; is an error.
  170. FB50    MOVE.B    D0,(A0)+    ;Always store the character
  171.     CMPI.B    #CR,D0        ;Was it a carriage return?
  172.     BEQ.S    FB90        ;Exit if it was
  173.     CMPA.L    #LINBUFE-1,A0    ;Is the buffer full? (leave room for CR)
  174.     BLO.S    FB85        ;Branch if it is not - go echo char
  175. FB80    SUBQ.L    #1,A0        ;Move fill pointer back
  176.     MOVEQ    #BEL,D0        ;Buffer is full so just beep
  177. FB85    BSR    CHOUT1
  178.     BRA    FB00        ;Loop until carriage return
  179.  
  180. FB90    BSR    CHOUT1        ;Echo the carriage return
  181.     RTS
  182.  
  183. ;----------------------------------------------------------------------
  184. ;Delete the line buffer. This deletes it from the screen and resets the
  185. ; fill pointer (A0) to the beginning of the buffer.
  186. ; Register D0 is destroyed.
  187. ;
  188. DELLINE    CMPA.L    #LINBUF,A0    ;Are we at the beginning of the buffer?
  189.     BEQ.S    DELL90        ;Branch if we are - we're all done
  190.     SUBQ.L    #1,A0        ;Backup one character in the line buffer
  191.     MOVEQ    #BS,D0        ;Delete the character on the screen:
  192.     BSR    CHOUT1        ; back up
  193.     MOVEQ    #SPACE,D0    ; space it out
  194.     BSR    CHOUT1
  195.     MOVEQ    #BS,D0        ; back up
  196.     BSR    CHOUT1
  197.     BRA.S    DELLINE        ;Loop for all characters
  198.  
  199. DELL90    RTS
  200.  
  201. ;----------------------------------------------------------------------
  202. ;Output character in D0 to the terminal
  203. ;
  204. CHOUT0    BRA    CHOUT1        ;(PBRA) same as for device # 1
  205.  
  206. ;----------------------------------------------------------------------
  207. ;Close the terminal
  208. ;
  209. CLOSE0    BRA    CLOSE1        ;(PBRA) same as for device # 1
  210.  
  211. ;======================================================================
  212. ;Unbuffered console handler (device #1)
  213. ;
  214. CONHAN1    DC.L    OPENI1        ;0 = OPENI
  215.     DC.L    OPENO1        ;1 = OPENO
  216.     DC.L    CHIN1        ;2 = CHIN
  217.     DC.L    CHOUT1        ;3 = CHOUT
  218.     DC.L    CLOSE1        ;4 = CLOSE
  219.     DC.L    GETINFO        ;5 = Get info
  220.     DC.L    DUMMY        ;6 = Spare
  221.     DC.L    CURSOR1        ;7 = Position cursor
  222.     DC.L    CHKUSR        ;8 = Check for CTRL-C, CTRL-S, CTRL-P
  223.     DC.L    GETKEYZ        ;9 = Wait for and return a key's value
  224.     DC.L    KEYHIT        ;10 = D0 = 'true' if key was hit
  225.     DC.L    SHOCUR        ;11 = Turns the cursor on/off
  226.     DC.L    BUTES        ;12 = Set display attributes
  227.  
  228. ;----------------------------------------------------------------------
  229. ;Open (initialize) keyboard for input.
  230. ; This will discard any characters in the type ahead buffer.
  231. ;
  232. OPENI1    BSR    OPENI        ;Initialize low-level input routines
  233.  
  234.     MOVE.L    D0,-(SP)    ;Save D0
  235.     MOVEQ    #FALSE,D0    ;Turn off the cursor flasher
  236.     BSR    SHOCUR
  237.  
  238. OPI105    BSR    KEYHIT        ;Is a key pressed?
  239.     BEQ.S    OPI110        ;Branch if not
  240.     BSR    GETKEYX        ;If so, eat it (check for CTRL-C, etc.)
  241.     BRA.S    OPI105        ;Loop unitl all characters are flushed
  242.  
  243. OPI110    MOVE.L    (SP)+,D0    ;Restore D0
  244. DUMMY    RTS
  245.  
  246. ;----------------------------------------------------------------------
  247. ;Open (initialize) terminal screen for output.
  248. ;
  249. OPENO1    MOVE.L    D0,-(SP)    ;Save D0
  250.  
  251.     BSR    OPENO        ;Initialize low-level output routines
  252.  
  253.     MOVEQ    #FALSE,D0    ;Turn off the cursor flasher
  254.     BSR    SHOCUR
  255.     BSR    CRLF1        ;Move to the start of a new line
  256.  
  257.     MOVE.L    (SP)+,D0    ;Restore D0
  258.     RTS
  259.  
  260. ;----------------------------------------------------------------------
  261. ;Get a character from the keyboard, echo it, and return it in D0.
  262. ;
  263. CHIN1    BSR    GETKEYX        ;Get the char (check for CTRL-C, etc.)
  264.     BRA    CHOUT1        ;(PBRA) Echo it
  265.  
  266. ;----------------------------------------------------------------------
  267. ;Output the character in D0.
  268. ; Handle some special characters: BELL, TAB, CR, & FF.
  269. ;
  270. CHOUT1    CMPI.B    #$20,D0        ;Is it a control character?
  271.     BHS    BYTEOUT        ;(PBHS) Branch if not
  272.  
  273.     CMPI.B    #TAB,D0        ;Is it a TAB character?
  274.     BNE.S    CHO120        ;Branch if not
  275.     BRA    DOTAB        ;(PBRA) do tab and return
  276. CHO120
  277.     CMPI.B    #CR,D0        ;Is it a carriage return?
  278.     BNE.S    CHO130        ;Branch if not
  279.     BRA    CRLF1        ;(PBRA) Start a new line
  280. CHO130
  281.     CMPI.B    #FF,D0        ;Is it a form feed?
  282.     BNE.S    CHO140        ;Branch if not
  283.     BRA    HOMER        ;(PBRA) Do home erase and return
  284. CHO140
  285.     CMPI.B    #BEL,D0        ;Is it a bell?
  286.     BNE.S    CHO150        ;Branch if not
  287.     BRA    BEEP        ;(PBRA) Make beep noise and return
  288. CHO150
  289.     CMPI.B    #LF,D0        ;Is it a line feed?
  290.     BNE.S    CHO160        ;Branch if not
  291.     RTS            ;Ignore it (these are still a problem)
  292. CHO160
  293.     CMPI.B    #BS,D0        ;Is it a backspace?
  294.     BNE.S    CHO170        ;Branch if not
  295.     SUBQ.W    #8,X0+2        ;Decrement X position
  296.     RTS            ;WARNING: THIS CAN UNDERFLOW ??
  297. CHO170
  298.     BRA    BYTEOUT        ;(PBRA) Output the character and return
  299.  
  300. ;----------------------------------------------------------------------
  301. ;Close the terminal (nothing required).
  302. ;
  303. CLOSE1    RTS
  304.  
  305. ;----------------------------------------------------------------------
  306. ;Return the address of the information array in D0
  307. ;
  308. GETINFO    MOVE.L    #INFO,D0
  309.     RTS
  310.  
  311. INFO    DC.L    START        ;0 Starting and ending addresses of
  312.     DC.L    END        ;1  this handler
  313.     DC.L    INFOSTR        ;2 Description
  314.     DC.L    FONT        ;3 Address of font table
  315.     DC.L    0        ;4 (not used)
  316.     DC.L    $00240EC9    ;5 Colors: background (high), text (low)
  317.     DC.L    $08800000    ;6 Cursor color
  318. INFOSTR    ASCII    'AMIGAHAN  AUG-06-90  Amiga console handler'
  319.     DC.B    0
  320.  
  321. ;----------------------------------------------------------------------
  322. ;Position the cursor to X,Y.
  323. ;Inputs:
  324. ; High byte of D0 =  X = Column
  325. ; Low byte of D0  =  Y = Line =
  326. ;
  327. ;Register usage: 
  328. ; D1 = Cursor X position
  329. ; D2 = Cursor Y position
  330. ;
  331. CURSOR1    MOVEM.L    D0-D2,-(SP)    ;Save registers
  332.  
  333.     MOVEQ    #0,D2        ;Cursor Y position
  334.     MOVE.B    D0,D2        ;D2.L = Y
  335.     ROR.W    #8,D0
  336.     MOVEQ    #0,D1        ;Cursor X position
  337.     MOVE.B    D0,D1        ;D1.L = X
  338.  
  339.     MOVE.W    WIDTH+2,D0    ;D0:= WIDTH/8
  340.     LSR.W    #3,D0        ;Width in characters
  341. CUR10    CMP.B    D0,D1        ;Check for limits
  342.     BLO.S    CUR20
  343.     SUB.B    D0,D1
  344.     BRA.S    CUR10
  345. CUR20
  346.     MOVE.L    HEIGHT,D0    ;D0:= HEIGHT/FHEIGHT
  347.     DIVU    FHEIGHT+2.L,D0    ;Height in characters
  348. CUR30    CMP.B    D0,D2
  349.     BLO.S    CUR40
  350.     SUB.B    D0,D2
  351.     BRA.S    CUR30
  352. CUR40
  353.     ASL.W    #3,D1        ;X0:= D1 *8  (8 = FWIDTH)
  354.     MOVE.W    D1,X0+2
  355.  
  356.     MULU    FHEIGHT+2.L,D2    ;Y0:= D2 * FHEIGHT
  357.     MOVE.W    D2,Y0+2
  358.  
  359.     MOVEM.L    (SP)+,D0-D2    ;Restore registers
  360.     RTS
  361.  
  362. ;----------------------------------------------------------------------
  363. ;Check for and handle CTRL-S, CTRL-P, and CTRL-C.
  364. ;
  365. CHKUSR    TST.B    CHKUSRF        ;Is CHKUSR disabled (usually by ED)?
  366.     BEQ.S    CKU99        ;Branch if so - exit
  367.  
  368.     MOVEM.L    D0/A0,-(SP)    ;Save registers
  369.  
  370.     BSR    KEYHIT        ;Was a key pressed?
  371.     BEQ.S    CKU90        ;Branch if not - exit
  372.  
  373.     MOVEA.L    KEYFILL-@-2(PC),A0 ;Get last keystroke in circular (type
  374.     SUBQ.L    #1,A0        ; ahead) buffer. Backup a character
  375.     CMPA.L    #KEYSTRT,A0    ;Did we back out of the buffer?
  376.     BHS.S    CKU10        ;Branch if not
  377.     MOVEA.L    #KEYEND-1,A0    ;Point to last char in circular buffer
  378. CKU10    MOVE.B    (A0),D0        ;Get last keystroke character
  379.  
  380.     CMPI.B    #'C'-CTRL,D0    ;Is it a CTRL-C?
  381.     BNE.S    CKU20        ;Branch if not
  382.     MOVE.L    A0,KEYFILL.L    ;Eat the CTRL-C
  383.     MOVEM.L    (SP)+,D0/A0    ;Restore registers (be conservative)
  384.     JMP    VEXIT        ;Take program exit vector
  385. CKU20
  386.     CMPI.B    #'P'-CTRL,D0    ;Is it a CTRL-P?
  387.     BNE.S    CKU30        ;Branch if not
  388.     MOVE.L    A0,KEYFILL.L    ;Eat the CTRL-P
  389.     MOVEM.L    (SP)+,D0/A0    ;Restore registers (be conservative)
  390.     JMP    VABORT        ;Take program abort vector
  391. CKU30
  392.     CMPI.B    #'S'-CTRL,D0    ;Is it a CTRL-S?
  393.     BNE.S    CKU90        ;Branch if not
  394.     MOVE.L    A0,KEYFILL.L    ;Eat the CTRL-P
  395. CKU35    CMPA.L    KEYFILL-@-2(PC),A0    ;Wait for a keystroke
  396.     BEQ.S    CKU35
  397.     MOVE.L    A0,KEYFILL.L    ;Eat this keystroke
  398.  
  399. CKU90    MOVEM.L    (SP)+,D0/A0    ;Restore registers
  400. CKU99    RTS
  401.  
  402. ;----------------------------------------------------------------------
  403. ;Get a character from the keyboard (or command file) and return it in D0
  404. ; check for CTRL-C, etc.
  405. ;
  406. GETKEYX    MOVEQ    #TRUE,D0    ;Turn on the cursor flasher
  407.     BSR    SHOCUR
  408.  
  409.     BSR    GETKEYZ        ;Get the character (from the keyboard
  410.                 ; or from a .CMD file)
  411.     MOVE.L    D0,-(SP)
  412.     MOVEQ    #FALSE,D0    ;Turn off the cursor flasher
  413.     BSR    SHOCUR
  414.     MOVE.L    (SP)+,D0
  415.  
  416.     CMPI.B    #'C'-CTRL,D0    ;Is it a CTRL-C?
  417.     BNE.S    GKX20        ;Branch if not
  418.     JMP    VEXIT        ;Take program exit vector
  419. GKX20
  420.     CMPI.B    #'P'-CTRL,D0    ;Is it a CTRL-P?
  421.     BNE.S    GKX30        ;Branch if not
  422.     JMP    VABORT        ;Take program abort vector
  423. GKX30
  424.     RTS
  425.  
  426. ;----------------------------------------------------------------------
  427. ;Get a character from the keyboard or command file and return it in D0.
  428. ; Command (.CMD) files are initiated by APEX.XPL (DOCMD), which fills
  429. ; the command buffer (CMDBUF) with the characters and sets the CMDMOD
  430. ; flag. The command buffer physically occupies the same space as the
  431. ; keyboard buffer, but they are logically two separate buffers.
  432. ;
  433. GETKEYZ    TST.B    CMDMOD        ;Are we in command mode?
  434.     BEQ.S    GKZ20        ;Branch if not
  435.  
  436.     MOVE.L    A6,-(SP)    ;Get character from command buffer
  437.     MOVEA.L    CMDPTR,A6    ; at CMDPTR
  438.     MOVEQ    #0,D0
  439.     MOVE.B    (A6)+,D0    ;Bump pointer and save it
  440.     MOVE.L    A6,CMDPTR
  441.     MOVEA.L    (SP)+,A6
  442.     CMPI.B    #EOF,D0        ;Is this the end of the command file?
  443.     BNE.S    GKZ90        ;Branch if not -- exit with char in D0
  444.     MOVE.B    #FALSE,CMDMOD    ;Turn off command mode
  445.  
  446. GKZ20    BSR    GETKEY        ;Get the character from keyboard
  447. GKZ90    RTS
  448.  
  449. ;----------------------------------------------------------------------
  450. ;Space over to next tab stop
  451. ;
  452. DOTAB    MOVE.L    D0,-(SP)    ;Save register
  453.  
  454. DOTAB10    MOVEQ    #SPACE,D0    ;Output a space character
  455.     BSR    BYTEOUT
  456.     MOVE.W    X0+2,D0        ;Are we at the next tab stop?
  457.     ANDI.B    #$38,D0        ;Every 8th character, 8 pixels wide
  458.     BNE.S    DOTAB10        ;Branch if not
  459.  
  460.     MOVE.L    (SP)+,D0    ;Restore register
  461.     RTS
  462.  
  463. ;----------------------------------------------------------------------
  464. ;Clear the screen and home to upper-left corner.
  465. ;
  466. HOMER    MOVEM.L    D0/A6,-(SP)    ;Save registers
  467.     JSR    CLEAR        ;(PJMP)
  468.     MOVEM.L    (SP)+,D0/A6    ;Restore registers
  469.     RTS
  470.  
  471. ;----------------------------------------------------------------------
  472. ;Start a new line on the terminal.
  473. ;
  474. CRLF1    CLR.W    X0+2        ;Reset X position to 0
  475.  
  476.     MOVE.W    D0,-(SP)
  477.     MOVE.W    FHEIGHT+2.L,D0    ;Move down a line
  478.     ADD.W    D0,Y0+2
  479.     MOVE.W    (SP)+,D0
  480.  
  481.     BRA    SCROLL        ;(PRBA) Check for scroll and adjust the
  482.                 ; cursor position if necessary
  483. ;----------------------------------------------------------------------
  484. ;Routine to turn the cursor indicator on/off.
  485. ; If D0 # 0 (true), the cursor is turned on.
  486. ;
  487. ;(Eventually add a sprite)
  488. SHOCUR
  489.     RTS
  490.  
  491. ;----------------------------------------------------------------------
  492. ;Set the display attributes according to D0.
  493. ; D0 contains a 4-bit array.
  494. ; (The terminal should be set up so that attributes are active to the
  495. ; end of the page.)
  496. ;
  497. BUTES
  498.     RTS
  499.  
  500. ;======================================================================
  501. ;Lowest level I/O routines:
  502. ;
  503. SCREEN    EQU    $60000        ;Address of screen buffer
  504. CHIPREG    EQU    $DFF000        ;Base address of chip registers
  505. ;Offsets to chip registers:
  506. DMACONR    EQU    $02        ;DMA control (and blitter status) read
  507. INTREQR    EQU    $1E        ;Interrupt request bits read
  508. BLTCON0    EQU    $40        ;Blitter control register 0
  509. BLTCON1    EQU    $42        ;Blitter control register 1
  510. BLTAFWM    EQU    $44        ;Blitter first word mask for source A
  511. BLTCPTH    EQU    $48        ;Blitter ptr to source C (high 3 bits)
  512. BLTAPTH    EQU    $50        ;Blitter ptr to source A (high 3 bits)
  513. BLTAPTL    EQU    $52        ;Blitter ptr to source A (low 15 bits)
  514. BLTDPTH    EQU    $54        ;Blitter ptr to destn. D (high 3 bits)
  515. BLTSIZE    EQU    $58        ;Blitter start and size (width, height)
  516. BLTCMOD    EQU    $60        ;Blitter modulo for source C
  517. BLTBMOD    EQU    $62        ;Blitter modulo for source B
  518. BLTAMOD    EQU    $64        ;Blitter modulo for source A
  519. BLTDMOD    EQU    $66        ;Blitter modulo for destn. D
  520. BLTBDAT    EQU    $72        ;Blitter source B data register
  521. BLTADAT    EQU    $74        ;Blitter source A data register
  522. COP1LCH    EQU    $80        ;Copper 1st location reg (high 3 bits)
  523. DIWSTRT    EQU    $8E        ;Display window start
  524. DIWSTOP    EQU    $90        ;Display window stop
  525. DDFSTRT    EQU    $92        ;Display bit plane data fetch start
  526. DDFSTOP    EQU    $94        ;Display bit plane data fetch stop
  527. DMACON    EQU    $96        ;DMA control write (clear or set)
  528. INTENA    EQU    $9A        ;Interrupt enable bits (clear or set)
  529. INTREQ    EQU    $9C        ;Interrupt request bits (clear or set)
  530. BPLCON0    EQU    $100        ;Bit plane control register 0
  531. BPLCON1    EQU    $102        ;Bit plane control register 1
  532. BPLCON2    EQU    $104        ;Bit plane control register 2
  533. BPL1MOD    EQU    $108        ;Bit plane modulo (odd planes)
  534. BPL2MOD    EQU    $10A        ;Bit plane modulo (even planes)
  535. COLOR00    EQU    $180        ;Color register 00
  536. COLOR01    EQU    $182        ;Color register 01
  537.  
  538. CIAA    EQU    $BFE001        ;Base address of 8520-A
  539. TALO    EQU    $400        ;Timer A low byte
  540. TAHI    EQU    $500        ;Timer A high byte
  541. SDR    EQU    $C00        ;Serial data register
  542. ICR    EQU    $D00        ;Interrupt control register
  543. CRA    EQU    $E00        ;Control register A
  544.  
  545. ;----------------------------------------------------------------------
  546. ;Routine to initialize the Amiga keyboard.
  547. ;
  548. OPENI    MOVE.L    A2,-(SP)    ;Save registers
  549.  
  550.     CLR.B    KEYDOWN.L    ;Assume all keys are up
  551.     ST    CHKUSRF        ;Enable CHKUSR (CTRL-C = abort, etc.)
  552.  
  553. ;Set up timer A for shifting out the keyboard handshake signal
  554.     LEA    CIAA.L,A2
  555.     CLR.B    CRA(A2)        ;Set serial input, timer A off
  556.     MOVE.B    #$7F,ICR(A2)    ;Clear all interrupts
  557.     MOVE.B    #$88,ICR(A2)    ;Set interrupts on serial port
  558. ;    MOVE.B    #$FF,SDR(A2)    ;Set handshake signal (true low)
  559.  
  560. ;    TST.B    SDR(A2)        ;Flush anything in the registers
  561. ;    TST.B    SDR(A2)        ; by reading them
  562. ;    BRA    XXXX        ;DEBUG
  563.  
  564.     LEA    KEYSTRT-@-2(PC),A2 ;Set the keyboard buffer empty
  565.     MOVE.L    A2,KEYFILL.L
  566.     MOVE.L    A2,KEYEMTY.L
  567.  
  568. ;    SUBA.L    A2,A2        ;A2:= 0
  569. ;LOOP    MOVE.L    #IRQ1HAN,(A2)+    ;Spurious
  570. ;    CMPA.W    #$0100,A2
  571. ;    BLO.S    LOOP
  572.  
  573. ;    MOVE.L    #IRQ1HAN,$64    ;1
  574.     MOVE.L    #IRQ2HAN,$68    ;2 set up interrupt vector for CIAA
  575. ;    MOVE.L    #IRQ3HAN,$6C    ;3
  576. ;    MOVE.L    #IRQ4HAN,$70    ;4
  577. ;    MOVE.L    #IRQ5HAN,$74    ;5
  578.     MOVE.L    #IRQ6HAN,$78    ;6 ignore spurious timer interrupt
  579. ;    MOVE.L    #IRQ7HAN,$7C    ;7
  580.     MOVE.L    #IRQ6HAN,$80    ;TRAP 0        DEBUG
  581.  
  582.     LEA    CHIPREG.L,A2
  583.     MOVE.W    #$7FFF,INTENA(A2)    ;Off
  584.     MOVE.W    #$C008,INTENA(A2)    ;INT2*
  585.     ANDI.W    #$F0FF,SR        ;Enable interrupts from keyboard
  586. ;XXXX                    ;DEBUG
  587.     MOVEA.L    (SP)+,A2
  588.     RTS
  589.  
  590. ;Dummy interrupt handlers -- just hang.
  591. IRQ1HAN
  592. ;IRQ2HAN
  593. IRQ3HAN
  594. IRQ4HAN
  595. IRQ5HAN
  596. IRQ6HAN
  597. IRQ7HAN
  598.     BRA    IRQ2HAN
  599.  
  600. ;----------------------------------------------------------------------
  601. ;Routine to initialize the Amiga display.
  602. ; (Note that INTA.68K routines destroy registers D0 and A6.)
  603. ;
  604. OPENO    MOVEM.L    D0/A1/A2/A5/A6,-(SP)    ;Save registers
  605.  
  606.     LEA    CHIPREG.L,A2    ;Point to chip registers
  607.     LEA    INFO.L,A1    ;Point to INFO array
  608.  
  609.     MOVE.W    5*4(A1),COLOR00(A2)    ;Get color register values from
  610.     MOVE.W    5*4+2(A1),COLOR01(A2)    ; INFO array
  611.  
  612.     LEA    PARAMS1-@-2(PC),A5    ;Point A5 to parameters
  613.     JSR    BITMAP        ;BITMAP(SCREEN, WIDTH, HEIGHT, DEPTH);
  614.  
  615.     LEA    PARAMS2-@-2(PC),A5    ;Point A5 to parameters
  616.     JSR    BITMAP2        ;BITMAP2(MAGNIFICATIONX,Y, OFFSETX,Y,
  617.                 ; INVERTX,Y)
  618.     LEA    PARAMS3-@-2(PC),A5    ;Point A5 to parameters
  619.     JSR    VIEW        ;VIEW(SCREEN, BPLCON0)
  620.  
  621.     MOVE.W    WIDTH+2,D0    ;CONWIDE:= WIDTH/8
  622.     ASR.W    #3,D0        ;(FWIDTH = 8)
  623.     MOVE.B    D0,CONWIDE
  624.  
  625.     MOVE.L    HEIGHT,D0    ;CONHIGH:= HEIGHT/FHEIGHT
  626.     DIVU    FHEIGHT+2.L,D0
  627.     MOVE.B    D0,CONHIGH
  628.  
  629.     MOVEM.L    (SP)+,D0/A1/A2/A5/A6    ;Restore registers
  630.     RTS
  631.  
  632. ;BITMAP(SCREEN, WIDTH, HEIGHT, DEPTH)
  633. PARAMS1    DC.L    SCREEN, 640, 240, 1
  634.  
  635. ;BITMAP2(MAGNIFICATIONX,Y, OFFSETX,Y, INVERTX,Y)
  636. PARAMS2    DC.L    0, 0, 0, 0, FALSE, FALSE
  637.  
  638. ;VIEW(SCREEN, $9004)
  639. PARAMS3    DC.L    SCREEN, $9000    ;Hires, one bit plane
  640.  
  641. ;----------------------------------------------------------------------
  642. ;Output the character in D0 and bump the cursor position, scroll if
  643. ; necessary.
  644. ;
  645. BYTEOUT    MOVEM.L    D0-D1/A0-A1,-(SP)    ;Save registers
  646.  
  647.     BSR    CHKUSR        ;Check for CTRL-C etc.
  648.  
  649.     MOVEQ    #0,D1        ;Point A0 to character in font table
  650.     MOVE.B    D0,D1        ;A0= (D0 - $20) *8 + FONT
  651.     SUBI.B    #$20,D1
  652.     LSL.W    #3,D1        ;*8, font is 8 dots wide
  653.     LEA    FONT.L,A0
  654.     LEA    0(A0,D1.W),A0
  655.  
  656.     LEA    CHIPREG.L,A1    ;Set register base (it's efficient)
  657. BYO05    MOVE.W    DMACONR(A1),D0    ;Wait for blitter not busy
  658.     BTST    #14,D0        ;(Don't display anything while
  659.     BNE.S    BYO05        ; the screen might be clearing)
  660.  
  661.     MOVE.W    X0+2,D1        ;Is cursor in the middle of a byte?
  662.     MOVE.W    D1,D0
  663.     ANDI.W    #$0007,D0
  664.     BNE    BYO10        ;Branch if so
  665.  
  666. ;Normal case: X position is on a byte boundary
  667. ;A0 points character's graphics in the FONT table
  668.     MOVE.W    Y0+2,D0        ;Point A1 to position on RASTER
  669.     MULU    WIDTH+2,D0    ;A1:= Y0 *WIDTH/8 + X0 /8 + RASTER
  670.     LSR.L    #3,D0
  671.     ASR.W    #3,D1
  672.     ADD.W    D1,D0
  673.     ADD.L    RASTER,D0
  674.     MOVEA.L    D0,A1
  675.  
  676.     MOVE.L    WIDTH,D0    ;Amount to add to move down a pixel
  677.     LSR.L    #3,D0        ;WIDTH/8
  678.  
  679.     MOVEQ    #7,D1        ;For D1:= 7 downto 0 do...
  680. BYO07    MOVE.B    (A0)+,(A1)    ;Move 8 bytes from FONT table to RASTER
  681.     ADDA.L    D0,A1
  682.     DBF    D1,BYO07
  683.     BRA    BYO90        ;Exit
  684. BYO10
  685.     MOVEM.L    D2-D5,-(SP)    ;Save extra registers
  686. ; Register usage:
  687. ;    D2 = Number of bits to shift right
  688. ;    D3 = Mask
  689. ;    D4 = Amount to add to screen address to move down a pixel
  690. ;    D5 = Loop counter
  691.  
  692.     MOVE.W    X0+2,D2
  693.     AND.W    #$000F,D2    ;D2= number of times to shift font right
  694.  
  695.     MOVE.L    #$00FFFFFF,D3    ;Set up mask (FWIDTH = 8)
  696.     ROR.L    D2,D3        ;Shift notch into position
  697.  
  698.     MOVE.W    Y0+2,D0        ;Point A1 to the long word on RASTER
  699.     MULU    WIDTH+2,D0    ; which will contain the font graphics
  700.     LSR.L    #3,D0        ;A1:= Y0 *WIDTH/8 + (X0 /8 &$FFFE) +
  701.     MOVE.W    X0+2,D1        ; RASTER
  702.     ASR.W    #3,D1
  703.     ANDI.W    #$FFFE,D1    ;A1 must point to a word boundary
  704.     ADD.W    D1,D0        ; because of the way the 68000 accesses
  705.     ADD.L    RASTER,D0    ; memory
  706.     MOVEA.L    D0,A1
  707.  
  708.     MOVE.L    WIDTH,D4    ;Amount to add to move down a pixel
  709.     LSR.L    #3,D4        ;D4:= WIDTH/8
  710.     MOVEQ    #7,D5        ;For D5:= 0 to 5 do...
  711. BYO20    MOVEQ    #0,D0        ;Clear high bytes
  712.     MOVE.B    (A0)+,D0    ;Get a byte of font graphics
  713.     ROR.L    #8,D0        ;Shift it into position
  714.     LSR.L    D2,D0
  715.     MOVE.L    (A1),D1        ;Get long word from screen
  716.     AND.L    D3,D1        ;Mask out a place for font
  717.     OR.L    D0,D1        ;Combine font with screen bits
  718.     MOVE.L    D1,(A1)        ;Store back on screen
  719.     ADDA.L    D4,A1        ;Move down a pixel
  720.     DBF    D5,BYO20    ;Loop
  721.  
  722.     MOVEM.L    (SP)+,D2-D5    ;Restore extra registers
  723.  
  724. BYO90    MOVEM.L    (SP)+,D0-D1/A0-A1    ;Restore registers
  725.     ADDI.W    #8,X0+2        ;Move cursor ahead 8 pixels
  726.                 ;(PFALL) Fall into SCROLL routine
  727. ;----------------------------------------------------------------------
  728. ;Check for scroll and do it if necessary.
  729. ;
  730. SCROLL    MOVE.W    D0,-(SP)    ;Save D0.W
  731.  
  732.     MOVE.W    X0+2,D0        ;Is the cursor beyond the end of line?
  733.     ADDQ.W    #7,D0        ;Don't break character in half
  734.     CMP.W    WIDTH+2,D0
  735.     BLO.S    SCR20        ;Branch if not
  736.     CLR.W    X0+2        ;Move to the beginning of the next line
  737.     MOVE.W    FHEIGHT+2.L,D0
  738.     ADD.W    D0,Y0+2
  739. SCR20
  740.     MOVE.W    Y0+2,D0        ;Is the cursor beyond the bottom line?
  741.     ADDI.W    #9,D0        ;Don't break character in half
  742.     CMP.W    HEIGHT+2,D0
  743.     BLO.S    SCR40        ;Branch if not.
  744.     BSR.S    SCROLLX        ;Scroll the screen up one line
  745.     MOVE.W    HEIGHT+2,D0    ;Set cursor to the bottom line
  746.     SUB.W    FHEIGHT+2.L,D0    ;Y0:= HEIGHT - FHEIGHT
  747.     MOVE.W    D0,Y0+2
  748. SCR40
  749.     MOVE.W    (SP)+,D0    ;Restore D0.W
  750.     RTS
  751.  
  752. ;----------------------------------------------------------------------
  753. ;Scroll the screen up one line and blank the bottom line. This uses the
  754. ; blitter.
  755. ;
  756. SCROLLX    MOVEM.L    D0-D1/A0,-(SP)    ;Save registers
  757.  
  758.     LEA    CHIPREG.L,A0    ;Set register base (it's efficient)
  759.     MOVE.W    #$8440,DMACON(A0) ;Enable blitter DMA (be nasty)
  760.  
  761. SCRX10    MOVE.W    DMACONR(A0),D0    ;Wait for blitter not busy
  762.     BTST    #14,D0        ;(Don't change the blitter registers
  763.     BNE.S    SCRX10        ; while it's doing something)
  764.  
  765.     MOVE.W    WIDTH+2,D0    ;Point to 2nd text line
  766.     LSR.W    #3,D0        ;RASTER + WIDTH/8 *FHEIGHT
  767.     MULU    FHEIGHT+2.L,D0
  768.     ADD.L    RASTER,D0
  769.     MOVE.L    D0,BLTAPTH(A0)
  770.  
  771.     MOVE.L    RASTER,BLTDPTH(A0)    ;Point destn. to 1st text line
  772.  
  773.     MOVEQ    #0,D0
  774.     MOVE.W    D0,BLTAMOD(A0)    ;Modulo = 0
  775.     MOVE.W    D0,BLTDMOD(A0)
  776.     MOVE.W    D0,BLTCON1(A0)
  777.     MOVEQ    #$FFFFFFFF,D0    ;No masking
  778.     MOVE.L    D0,BLTAFWM(A0)    ;(Also sets BLTALWM)
  779.     MOVE.W    #$09F0,BLTCON0(A0) ;Use A & D, D:= A
  780.  
  781.     MOVE.W    HEIGHT+2,D0    ;(HEIGHT - FHEIGHT) << 6 + WIDTH/16
  782.     SUB.W    FHEIGHT+2.L,D0
  783.     LSL.W    #6,D0
  784.     MOVE.W    WIDTH+2,D1
  785.     LSR.W    #4,D1
  786.     OR.W    D1,D0
  787.     MOVE.W    D0,BLTSIZE(A0)
  788.  
  789. SCRX20    MOVE.W    DMACONR(A0),D0    ;Wait for blitter not busy
  790.     BTST    #14,D0        ;(Don't change the blitter registers
  791.     BNE.S    SCRX20        ; while it's doing something)
  792.  
  793.     MOVE.W    #$0100,BLTCON0(A0)    ;Use D
  794.     MOVE.W    FHEIGHT+2.L,D0    ;FHEIGHT << 6 + WIDTH/16
  795.     LSL.W    #6,D0
  796.     MOVE.W    WIDTH+2,D1
  797.     LSR.W    #4,D1
  798.     OR.W    D1,D0
  799.     MOVE.W    D0,BLTSIZE(A0)
  800.  
  801. SCRX30    MOVE.W    DMACONR(A0),D0    ;Wait for blitter not busy
  802.     BTST    #14,D0        ;(Don't allow writting while it's being
  803.     BNE.S    SCRX30        ; cleared)
  804.  
  805.     MOVEM.L    (SP)+,D0-D1/A0    ;Restore registers
  806.     RTS
  807.  
  808. ;----------------------------------------------------------------------
  809. ;Make a beep noise. Approximately 1KHz for 0.1 second.
  810. ; (The hardware manual lies: the processor cannot control sound by
  811. ; writing directly to AUDXDAT.)
  812. ;
  813. AUD0LC    EQU    $A0        ;Pointer to waveform table (18 bits)
  814. AUD0LEN    EQU    $A4        ;Length of waveform table (words)
  815. AUD0PER    EQU    $A6        ;Sample period, 280ns per count
  816. AUD0VOL    EQU    $A8        ;Audio channel volume control
  817.  
  818. BEEP    MOVEM.L    D0/A0,-(SP)    ;Save registers
  819.  
  820.     LEA    CHIPREG.L,A0    ;Point to base of chip registers
  821.     MOVE.L    #WAVETBL,AUD0LC(A0) ;Set pointer to wave table
  822.     MOVE.W    #4,AUD0LEN(A0)    ;Set table length (words)
  823.     MOVE.W    #446,AUD0PER(A0) ;Set sample period (446 *280ns)
  824.     MOVE.W    #$0040,AUD0VOL(A0) ;Set maximum volume
  825.     MOVE.W    #$8201,DMACON(A0) ;Enable audio channel 0 DMA
  826.  
  827.     MOVEQ    #-1,D0        ;Delay about 0.1 second
  828. BEEP10    DBF    D0,BEEP10
  829.  
  830.     MOVE.W    #$0001,DMACON(A0) ;Disable audio channel 0 DMA
  831.  
  832.     MOVEM.L    (SP)+,D0/A0    ;Restore registers
  833.     RTS
  834.  
  835. WAVETBL    DC.W    $0060, $7F60, $00E0, $80E0
  836.  
  837. ;----------------------------------------------------------------------
  838. ;Character fonts for 8 x 8 cells.
  839. ; Format:
  840. ;        MSB             LSB
  841. ;   first byte     .  .  *  *  *  *  .  .
  842. ;         .  *  .  .  .  .  *  .
  843. ;         .  .  .  .  .  .  *  .
  844. ;         .  .  .  *  *  *  .  .
  845. ;         .  .  *  .  .  .  .  .
  846. ;         .  *  .  .  .  .  .  .
  847. ;         .  *  *  *  *  *  *  .
  848. ;    last byte     .  .  .  .  .  .  .  .
  849. ;
  850. ;
  851. FHEIGHT    DC.L    10    ;Height of font including space between lines
  852. ;FWIDTH    DC.L    8    ;Not used - width is cast in concrete
  853.  
  854. FONT
  855. ;    DC.B    $00, $00, $FF, $00, $00, $FF, $00, $00    ;===
  856. ;    DC.B    $10, $10, $1F, $10, $10, $1F, $10, $10    ; |=
  857. ;    DC.B    $10, $10, $FF, $10, $10, $FF, $10, $10    ;=|=
  858. ;    DC.B    $10, $10, $F0, $10, $10, $F0, $10, $10    ;=|
  859. ;    DC.B    $01, $02, $04, $08, $10, $20, $40, $80    ; /
  860. ;    DC.B    $80, $40, $20, $10, $08, $04, $02, $01    ; \
  861. ;    DC.B    $81, $42, $24, $18, $18, $24, $42, $81    ; x
  862. ;    DC.B    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF    ;block (cursor)
  863. ;    DC.B    $00, $20, $40, $FE, $40, $20, $00, $00    ;<--
  864. ;    DC.B    $0C, $12, $12, $12, $0C, $00, $00, $00    ; 0
  865. ;    DC.B    $10, $10, $10, $10, $54, $38, $10, $00    ;down arrow
  866. ;    DC.B    $10, $38, $54, $10, $10, $10, $10, $00    ;up arrow
  867. ;    DC.B    $00, $08, $04, $FE, $04, $08, $00, $00    ;-->
  868. ;    DC.B    $0C, $12, $04, $08, $1E, $00, $00, $00    ; 2
  869. ;    DC.B    $10, $10, $10, $F0, $00, $00, $00, $00    ;low-rt corner
  870. ;    DC.B    $10, $10, $10, $FF, $10, $10, $10, $10    ; +
  871. ;
  872. ;    DC.B    $10, $10, $10, $FF, $00, $00, $00, $00    ;-'-
  873. ;    DC.B    $00, $00, $00, $FF, $10, $10, $10, $10    ;-,-
  874. ;    DC.B    $10, $10, $10, $F0, $10, $10, $10, $10    ;-|
  875. ;    DC.B    $10, $10, $10, $1F, $10, $10, $10, $10    ; |-
  876. ;    DC.B    $FF, $00, $00, $00, $00, $00, $00, $00    ;---
  877. ;    DC.B    $00, $00, $00, $FF, $00, $00, $00, $00    ;---
  878. ;    DC.B    $10, $10, $10, $10, $10, $10, $10, $10    ; |
  879. ;    DC.B    $01, $01, $01, $01, $01, $01, $01, $01    ;  |
  880. ;    DC.B    $00, $00, $00, $1F, $10, $10, $10, $10    ;up-lt corner
  881. ;    DC.B    $00, $00, $00, $F0, $10, $10, $10, $10    ;up-rt corner
  882. ;    DC.B    $10, $10, $10, $1F, $00, $00, $00, $00    ;low-lt corner
  883. ;    DC.B    $10, $10, $10, $F0, $00, $00, $00, $00    ;low-rt corner
  884. ;    DC.B    $00, $00, $00, $03, $04, $08, $10, $10    ;up-lt curve
  885. ;    DC.B    $00, $00, $00, $80, $40, $20, $10, $10    ;up-rt curve
  886. ;    DC.B    $10, $08, $04, $03, $00, $00, $00, $00    ;low-lt curve
  887. ;    DC.B    $10, $20, $40, $80, $00, $00, $00, $00    ;low-rt curve
  888. ;
  889.     DC.B    $00, $00, $00, $00, $00, $00, $00, $00    ;space
  890.     DC.B    $18, $18, $18, $18, $18, $00, $18, $00    ;!
  891.     DC.B    $6C, $6C, $00, $00, $00, $00, $00, $00    ;"
  892.     DC.B    $6C, $6C, $FE, $6C, $FE, $6C, $6C, $00    ;#
  893.     DC.B    $18, $3E, $68, $3C, $16, $7C, $18, $00    ;$
  894.     DC.B    $00, $C6, $CC, $18, $30, $66, $C6, $00    ;%
  895.     DC.B    $38, $6C, $6C, $38, $7A, $CC, $76, $00    ;&
  896.     DC.B    $38, $18, $30, $00, $00, $00, $00, $00    ;'
  897.     DC.B    $0C, $18, $30, $30, $30, $18, $0C, $00    ;(
  898.     DC.B    $30, $18, $0C, $0C, $0C, $18, $30, $00    ;)
  899.     DC.B    $00, $66, $3C, $7E, $3C, $66, $00, $00    ;*
  900.     DC.B    $00, $18, $18, $7E, $18, $18, $00, $00    ;+
  901.     DC.B    $00, $00, $00, $00, $00, $38, $18, $30    ;,
  902.     DC.B    $00, $00, $00, $7E, $00, $00, $00, $00    ;-
  903.     DC.B    $00, $00, $00, $00, $00, $18, $18, $00    ;.
  904.     DC.B    $00, $06, $0C, $18, $30, $60, $C0, $00    ;/
  905.  
  906.     DC.B    $3C, $66, $6E, $7E, $76, $66, $3C, $00    ;0
  907.     DC.B    $18, $38, $18, $18, $18, $18, $3C, $00    ;1
  908.     DC.B    $3C, $66, $06, $0C, $38, $60, $7E, $00    ;2
  909.     DC.B    $7E, $0C, $18, $3C, $06, $66, $3C, $00    ;3
  910.     DC.B    $0E, $1E, $36, $66, $7F, $06, $06, $00    ;4
  911.     DC.B    $7E, $60, $7C, $06, $06, $66, $3C, $00    ;5
  912.     DC.B    $1C, $30, $60, $7C, $66, $66, $3C, $00    ;6
  913.     DC.B    $7E, $46, $06, $0C, $18, $18, $18, $00    ;7
  914.     DC.B    $3C, $66, $66, $3C, $66, $66, $3C, $00    ;8
  915.     DC.B    $3C, $66, $66, $3E, $0C, $18, $30, $00    ;9
  916.     DC.B    $00, $18, $18, $00, $18, $18, $00, $00    ;:
  917.     DC.B    $00, $18, $18, $00, $18, $18, $18, $30    ;;
  918.     DC.B    $0C, $18, $30, $60, $30, $18, $0C, $00    ;<
  919.     DC.B    $00, $00, $7E, $00, $7E, $00, $00, $00    ;=
  920.     DC.B    $60, $30, $18, $0C, $18, $30, $60, $00    ;>
  921.     DC.B    $3C, $66, $06, $0C, $18, $00, $18, $00    ;?
  922.  
  923.     DC.B    $3C, $66, $6E, $6A, $6E, $60, $3C, $00    ;@
  924.     DC.B    $18, $3C, $66, $66, $7E, $66, $66, $00    ;A
  925.     DC.B    $7C, $66, $66, $7C, $66, $66, $7C, $00    ;B
  926.     DC.B    $3C, $66, $60, $60, $60, $66, $3C, $00    ;C
  927.     DC.B    $78, $6C, $66, $66, $66, $6C, $78, $00    ;D
  928.     DC.B    $7E, $60, $60, $7C, $60, $60, $7E, $00    ;E
  929.     DC.B    $7E, $60, $60, $7C, $60, $60, $60, $00    ;F
  930.     DC.B    $3E, $60, $60, $60, $6E, $66, $3E, $00    ;G
  931.     DC.B    $66, $66, $66, $7E, $66, $66, $66, $00    ;H
  932.     DC.B    $3C, $18, $18, $18, $18, $18, $3C, $00    ;I
  933.     DC.B    $06, $06, $06, $06, $06, $66, $3C, $00    ;J
  934.     DC.B    $66, $6C, $78, $70, $78, $6C, $66, $00    ;K
  935.     DC.B    $60, $60, $60, $60, $60, $60, $7E, $00    ;L
  936.     DC.B    $C6, $EE, $FE, $D6, $C6, $C6, $C6, $00    ;M
  937.     DC.B    $66, $66, $76, $7E, $6E, $66, $66, $00    ;N
  938.     DC.B    $3C, $66, $66, $66, $66, $66, $3C, $00    ;O
  939.  
  940.     DC.B    $7C, $66, $66, $7C, $60, $60, $60, $00    ;P
  941.     DC.B    $3C, $66, $66, $66, $66, $6E, $3C, $06    ;Q
  942.     DC.B    $7C, $66, $66, $7C, $78, $6C, $66, $00    ;R
  943.     DC.B    $3C, $66, $60, $3C, $06, $66, $3C, $00    ;S
  944.     DC.B    $7E, $18, $18, $18, $18, $18, $18, $00    ;T
  945.     DC.B    $66, $66, $66, $66, $66, $66, $3C, $00    ;U
  946.     DC.B    $66, $66, $66, $3C, $3C, $18, $18, $00    ;V
  947.     DC.B    $C6, $C6, $C6, $D6, $EE, $C6, $82, $00    ;W
  948.     DC.B    $66, $66, $3C, $18, $3C, $66, $66, $00    ;X
  949.     DC.B    $66, $66, $66, $3C, $18, $18, $18, $00    ;Y
  950.     DC.B    $7E, $06, $0C, $18, $30, $60, $7E, $00    ;Z
  951.     DC.B    $3C, $30, $30, $30, $30, $30, $3C, $00    ;[
  952.     DC.B    $00, $C0, $60, $30, $18, $0C, $06, $00    ;\
  953.     DC.B    $3C, $0C, $0C, $0C, $0C, $0C, $3C, $00    ;]
  954.     DC.B    $10, $38, $6C, $C6, $00, $00, $00, $00    ;^
  955.     DC.B    $00, $00, $00, $00, $00, $00, $00, $FE    ;_
  956.  
  957.     DC.B    $38, $30, $18, $00, $00, $00, $00, $00    ;`
  958.     DC.B    $00, $00, $3C, $06, $3E, $66, $3F, $00    ;a
  959.     DC.B    $60, $60, $7C, $66, $66, $66, $7C, $00    ;b
  960.     DC.B    $00, $00, $3C, $66, $60, $62, $3C, $00    ;c
  961.     DC.B    $06, $06, $3E, $66, $66, $66, $3E, $00    ;d
  962.     DC.B    $00, $00, $3C, $66, $7E, $60, $3E, $00    ;e
  963.     DC.B    $1E, $30, $30, $7C, $30, $30, $30, $00    ;f
  964.     DC.B    $00, $00, $3E, $66, $66, $3E, $06, $7C    ;g
  965.     DC.B    $60, $60, $7C, $66, $66, $66, $66, $00    ;h
  966.     DC.B    $18, $00, $38, $18, $18, $18, $3C, $00    ;i
  967.     DC.B    $0C, $00, $0C, $0C, $0C, $0C, $CC, $78    ;j
  968.     DC.B    $60, $60, $66, $6C, $78, $6C, $66, $00    ;k
  969.     DC.B    $38, $18, $18, $18, $18, $18, $3C, $00    ;l
  970.     DC.B    $00, $00, $CC, $EE, $D6, $C6, $C6, $00    ;m
  971.     DC.B    $00, $00, $7C, $66, $66, $66, $66, $00    ;n
  972.     DC.B    $00, $00, $3C, $66, $66, $66, $3C, $00    ;o
  973.  
  974.     DC.B    $00, $00, $7C, $66, $66, $7C, $60, $60    ;p
  975.     DC.B    $00, $00, $3E, $66, $66, $3E, $06, $06    ;q
  976.     DC.B    $00, $00, $6E, $70, $60, $60, $60, $00    ;r
  977.     DC.B    $00, $00, $3E, $60, $3C, $06, $7C, $00    ;s
  978.     DC.B    $10, $30, $7C, $30, $30, $32, $1C, $00    ;t
  979.     DC.B    $00, $00, $66, $66, $66, $66, $3B, $00    ;u
  980.     DC.B    $00, $00, $66, $66, $66, $3C, $18, $00    ;v
  981.     DC.B    $00, $00, $C6, $C6, $D6, $7C, $6C, $00    ;w
  982.     DC.B    $00, $00, $C6, $6C, $38, $6C, $C6, $00    ;x
  983.     DC.B    $00, $00, $66, $66, $66, $3C, $18, $70    ;y
  984.     DC.B    $00, $00, $7E, $0C, $18, $30, $7E, $00    ;z
  985.     DC.B    $0E, $18, $18, $70, $18, $18, $0E, $00    ;{
  986.     DC.B    $18, $18, $18, $00, $18, $18, $18, $00    ;|
  987.     DC.B    $70, $18, $18, $0E, $18, $18, $70, $00    ;}
  988.     DC.B    $72, $9C, $00, $00, $00, $00, $00, $00    ;~
  989.     DC.B    $33, $CC, $33, $CC, $33, $CC, $33, $CC    ;box
  990.  
  991. ;======================================================================
  992. ;Keyboard routines:
  993. ;----------------------------------------------------------------------
  994. ;Wait for a keystroke then return its ASCII value in D0.
  995. ; This uses an interrupt handler to fill a circular (type-ahead) buffer.
  996. ;
  997. GETKEY    MOVE.L    A0,-(SP)    ;Save A0
  998.  
  999.     MOVEA.L    KEYEMTY-@-2(PC),A0 ;Get ASCII key from circular buffer
  1000. KI10    ADDQ.L    #1,HASH        ;Spin the randomizer while we wait
  1001.     CMPA.L    KEYFILL-@-2(PC),A0 ;Is there something in the buffer?
  1002.     BEQ.S    KI10        ;Branch if not -- wait for key code
  1003.  
  1004.     MOVEQ    #0,D0        ;Make sure high-order bytes are clear
  1005.     MOVE.B    (A0)+,D0    ;Get key code and bump empty pointer
  1006.     CMPA.L    #KEYEND,A0    ;Did empty pointer go beyond the end?
  1007.     BLO.S    KI30        ;Branch if not
  1008.     LEA    KEYSTRT-@-2(PC),A0 ;Wrap empty pointer to beginning
  1009. KI30    MOVE.L    A0,KEYEMTY.L    ;Save empty pointer
  1010.  
  1011.     MOVEA.L    (SP)+,A0    ;Restore A0
  1012.     RTS            ;Return with ASCII code in D0
  1013.  
  1014. ;----------------------------------------------------------------------
  1015. ;Routine to check if a key was struck. This returns with NE status if
  1016. ; it was struck. A boolean is also returned in D0 since this may be
  1017. ; called by an intrinsic. (Qualifier keys, such as SHIFT and CTRL, don't
  1018. ; count as keystrokes.)
  1019. ;
  1020. KEYHIT    MOVE.L    KEYFILL-@-2(PC),D0
  1021. KH10    CMP.L    KEYEMTY-@-2(PC),D0
  1022.     SNE    D0
  1023.     EXT.W    D0
  1024.     EXT.L    D0
  1025.     RTS
  1026.  
  1027.  
  1028. REPRATE    EQU    $7FFF        ;Auto-repeat repitition rate
  1029.                 ; (1000 => 16.6/sec))
  1030. KEYFLAG    DC.B    0        ;Bit array indicating key down for
  1031.                 ; SHIFT, CAPS, CTRL, ALT and A keys
  1032. KEYLAST    DC.B    0        ;Last ASCII key (for auto-repeat)
  1033. KEYDOWN    DC.B    0        ;Flag: ASCII key is pressed
  1034.  
  1035. KEYFILL    DS.L    1        ;Pointer used to fill circular buffer
  1036. KEYEMTY    DS.L    1        ;Pointer used to empty circular buffer
  1037. KEYSTRT    DS.B    10        ;Circular (type-ahead) buffer
  1038. KEYEND    EQU    @        ;End of buffer +1
  1039.  
  1040. ;----------------------------------------------------------------------
  1041. ;Keyboard interrupt handler. This routine gets the key code, converts
  1042. ; it to ASCII, and stores it into a circular buffer.
  1043. ;
  1044. ;The A keys are used as auto-repeat keys.
  1045. ; Pressing SHIFT while CAPS LOCK is true, will give lowercase letters.
  1046. ;
  1047. ;The hysterical, insubordinate keyboard must be given immediate
  1048. ; attention otherwise it will make some mighty assumptions for a mere
  1049. ; keyboard and go into resync mode, which will cause delays and false
  1050. ; key codes. This is a typical example of how an intelligent peripherial
  1051. ; out-smarts itself. This requires that an interrupt handler be used,
  1052. ; which serendipitously provides a type-ahead buffer.
  1053. ;
  1054. IRQ2HAN    MOVEM.L    D0/D1/A0,-(SP)    ;Save registers
  1055.  
  1056.     LEA    CHIPREG.L,A0    ;Point A0 to base of chip registers
  1057.     MOVE.W    #$0008,INTREQ(A0) ;Clear interrupt request
  1058.  
  1059. ;    ADDQ.W    #3,COLOR00(A0)    ;*** DEBUG ***
  1060.  
  1061.     LEA    CIAA.L,A0    ;Point A0 to base address of 8520-A
  1062.     MOVE.B    ICR(A0),D0    ;Get copy and clear interrupt bits
  1063.  
  1064.     BTST    #3,D0        ;Serial data received?
  1065.     BEQ    KB200        ;Branch if not
  1066.     MOVE.W    D0,-(SP)    ;Save interrupt status bits
  1067.  
  1068.     MOVEQ    #0,D0        ;Clear high bytes (for index below)
  1069.     MOVE.B    SDR(A0),D0    ;Read data from keyboard serial port
  1070.     ORI.B    #$40,CRA(A0)    ;Set to output from serial port
  1071.                 ; (handshake signal)
  1072.     NOT.B    D0        ;Re-invert the data
  1073.     ROR.B    #1,D0        ;Unscramble the bits
  1074.  
  1075.     CMPI.B    #$80,D0        ;Is it a release, (or comm?)
  1076.     BLO.S    KB10        ;Branch if not
  1077.  
  1078.     CMPI.B    #$E0,D0        ;Is it a comm or modifier?
  1079.     BHS.S    KB10        ;Branch if so
  1080.     CLR.B    KEYDOWN.L    ;Clear KEYDOWN to stop auto-repeat
  1081. KB10
  1082.     CMPI.B    #$60,D0        ;Is it a qualifier, release, or comm?
  1083.     BLO.S    KB20        ;Branch if not
  1084.  
  1085.     MOVE.B    D0,D1        ;Is it a qualifier key?
  1086.     ANDI.B    #$7F,D1        ; (i.e: $60-$67 or $E0-$E7)
  1087.     CMPI.B    #$60,D1
  1088.     BLO    KB100        ;Branch if not
  1089.     CMPI.B    #$67,D1
  1090.     BHI    KB100
  1091.  
  1092.                 ;Set or clear the flag bit which 
  1093.     SUBI.B    #$60,D0        ; corresponds to this qualifier key
  1094.  
  1095.     BCLR    #7,D0        ;D0: [0..7]
  1096.     BEQ.S    KB15        ;Branch if MSB was clear
  1097.     BCLR    D0,KEYFLAG.L    ;Key was released, clear flag bit
  1098.     BRA.S    KB18
  1099. KB15    BSET    D0,KEYFLAG.L    ;Key was pressed, set flag bit
  1100. KB18    BRA    KB100
  1101. KB20
  1102.     CMPI.B    #$50,D0        ;Is it a function or HELP key?
  1103.     BLO.S    KB30        ;Branch if not
  1104.     BRA    KB100        ;Ignore it
  1105. KB30
  1106.  
  1107.     CMPI.B    #$40,D0        ;Is it a control key?
  1108.     BLO.S    KB40        ;Branch if not
  1109.     LEA    KBTBL2.L,A0    ;Look up control keys in table
  1110.     SUBI.B    #$40,D0        ;Warning: high byte must be clear
  1111.     MOVE.B    0(A0,D0.W),D0
  1112.     BRA    KB80        ;Exit, checking for ALT key
  1113. KB40
  1114.     BTST    #0,KEYFLAG.L    ;Is the left SHIFT key down?
  1115.     BNE.S    KB41        ;Branch if it is
  1116.     BTST    #1,KEYFLAG.L    ;Is the right SHIFT key down?
  1117.     BEQ.S    KB50        ;Branch if not
  1118. KB41
  1119.     LEA    KBTBL1.L,A0    ;Look up shifted character
  1120.     MOVE.B    0(A0,D0.W),D0    ;WARNING (high byte must be clear)
  1121.     BRA.S    KB60        ;Go check for CAPS LOCK key
  1122. KB50
  1123.     LEA    KBTBL0.L,A0    ;Look up character
  1124.     MOVE.B    0(A0,D0.W),D0
  1125. KB60
  1126.     BTST    #2,KEYFLAG.L    ;Is the CAPS LOCK key down?
  1127.     BEQ.S    KB70        ;Branch if not
  1128.     CMPI.B    #'a',D0        ;Is character a lowercase letter?
  1129.     BLO.S    KB65        ;Branch if not
  1130.     CMPI.B    #'z',D0
  1131.     BHI.S    KB65
  1132.     ANDI.B    #$DF,D0        ;Convert to upper case
  1133.     BRA.S    KB70
  1134. KB65
  1135.     CMPI.B    #'A',D0        ;Is character an uppercase letter?
  1136.     BLO.S    KB70        ;Branch if not
  1137.     CMPI.B    #'Z',D0
  1138.     BHI.S    KB70
  1139.     ORI.B    #$20,D0        ;Convert to lower case
  1140. KB70
  1141.     BTST    #3,KEYFLAG.L    ;Is the CTRL key down?
  1142.     BEQ.S    KB80        ;Branch if not
  1143.  
  1144.     CMPI.B    #$38,D0        ;If CTRL-8 then toggle interlaced mode
  1145.     BNE.S    KB74
  1146.     MOVE.W    #240,D0        ;Assume toggle into non-interlaced mode
  1147.     BCHG    #2,PARAMS3+7.L    ;Test LACE bit in BPLCON0 word
  1148.     BNE.S    KB72        ;Branch if it was in LACE mode
  1149.     ADD.W    D0,D0        ;Double height for LACE mode
  1150. KB72    MOVE.W    D0,PARAMS1+10.L    ;Set height parameter
  1151.     BRA.S    KB77        ;Go open display with new parameters
  1152. KB74
  1153.     CMPI.B    #$39,D0        ;If CTRL-9 then toggle hires mode
  1154.     BNE.S    KB78
  1155.     MOVE.W    #320,D0        ;Assume toggle into lores mode
  1156.     BCHG    #7,PARAMS3+6.L    ;Test HIRES bit in BPLCON0 word
  1157.     BNE.S    KB76        ;Branch if it was in HIRES mode
  1158.     ADD.W    D0,D0        ;Double width for hires mode
  1159. KB76    MOVE.W    D0,PARAMS1+6.L    ;Set width parameter
  1160. KB77    BSR    OPENO1        ;Open display with new parameters
  1161.     BRA    KB100        ;Exit
  1162. KB78
  1163.     CMPI.B    #$40,D0        ;If $40-$7E then clear bits 5 & 6
  1164.     BLO.S    KB80        ; to make it a control character
  1165.     CMPI.B    #$7E,D0
  1166.     BHI.S    KB80
  1167.     ANDI.B    #$9F,D0
  1168. KB80
  1169.     BTST    #4,KEYFLAG.L    ;Is the left ALT key down?
  1170.     BNE.S    KB81        ;Branch if it is
  1171.     BTST    #5,KEYFLAG.L    ;Is the right ALT key down?
  1172.     BEQ.S    KB90        ;Branch if not
  1173. KB81
  1174.     ORI.B    #$80,D0        ;Set MSB
  1175. KB90
  1176.     MOVE.B    D0,KEYLAST.L    ;Save this ASCII key character in case
  1177.     ST    KEYDOWN.L    ; of auto-repeat
  1178.  
  1179.     BSR    KEY2BUF        ;Store key character in buffer
  1180.  
  1181. ;If auto-repeat key is down and an ASCII key is pressed then enable
  1182. ; auto-repeat interrupts.
  1183. KB100    LEA    CIAA.L,A0    ;Point A0 to base address of 8520-A
  1184.     TST.B    KEYDOWN.L    ;Is an ASCII key down?
  1185.     BEQ.S    KB120        ;Branch if not
  1186.     BTST    #6,KEYFLAG.L    ;Is an auto-repeat key down?
  1187.     BNE.S    KB110        ;Branch if it is
  1188.     BTST    #7,KEYFLAG.L
  1189.     BEQ.S    KB120        ;Branch if not
  1190.  
  1191. KB110    MOVE.B    #REPRATE/256,TAHI(A0)    ;Set timer repitition rate
  1192.     MOVE.B    #REPRATE\256,TALO(A0)
  1193.     MOVE.B    #$41,CRA(A0)    ;Start timer, force load, 02 input
  1194.     MOVE.B    #$81,ICR(A0)    ;Enable timer A interrupts
  1195.     BRA.S    KB130
  1196. KB120
  1197.     CLR.B    CRA(A0)        ;Stop timer
  1198. KB130
  1199.     MOVEQ    #75,D0        ;Wait a total of 75us (barf) for the
  1200. KB140    DBF    D0,KB140    ; handshake signal
  1201.  
  1202.     ANDI.B    #$BF,CRA(A0)    ;Set to input from serial port
  1203.  
  1204.     MOVE.W    (SP)+,D0    ;Restore interrupt bits 
  1205.  
  1206. ;Check for auto-repeat interrupt
  1207. KB200    BTST    #0,D0        ;Timer A interrupt?
  1208.     BEQ.S    KB230        ;Branch if not
  1209.  
  1210.     TST.B    KEYDOWN.L    ;Is an ASCII key down?
  1211.     BEQ.S    KB230        ;Branch if not
  1212.     MOVE.B    KEYLAST-@-2(PC),D0    ;Get the last ASCII key code
  1213.     BSR    KEY2BUF        ;Put it into the circular buffer
  1214. KB230
  1215.     MOVEM.L    (SP)+,D0/D1/A0    ;Restore registers
  1216.     RTE
  1217.  
  1218. ;These tables use the key code as an index to the ASCII equivalent.
  1219. ;Table of unshifted characters (key codes $00-$3F):
  1220. KBTBL0    ASCII    "`1234567890-=\?0"
  1221.     ASCII    "qwertyuiop[]?123"
  1222.     ASCII    "asdfghjkl;'??456"
  1223.     ASCII    "?zxcvbnm,./?.789"
  1224.  
  1225. ;Table of shifted characters (key codes $00-$3F).
  1226. ; Shifted keypad characters are IBM-style ED commands.
  1227. KBTBL1    ASCII    "~!@#$%^&*()_+|?"
  1228.     DC.B    $02        ;Word back
  1229.     ASCII    "QWERTYUIOP{}?"
  1230.     DC.B    $04, $13, $0A    ;End, line down, page down
  1231.     ASCII    'ASDFGHJKL:"??'
  1232.     DC.B    $11, $14, $01    ;Back char, show controls, char ahead
  1233.     ASCII    "?ZXCVBNM<>??"
  1234.     DC.B    $0E, $05, $17, $0B ;Word ahead, start, line up, page up
  1235.  
  1236. ;Table of control characters (key codes $40-$4F):
  1237. KBTBL2    DC.B    $20, $08, $09, $0D, $0D, $1B, $7F, $00
  1238.     DC.B    $00, $00, $2D, $00, $0B, $0A, $15, $08
  1239.  
  1240. ;----------------------------------------------------------------------
  1241. ;Store D0 into circular buffer (if it isn't full).
  1242. ; Register A0 is destroyed.
  1243. ;
  1244. KEY2BUF    MOVEA.L    KEYFILL-@-2(PC),A0 ;Store character into circular buffer
  1245.     MOVE.B    D0,(A0)+    ;Always store the character
  1246.     CMPA.L    #KEYEND,A0    ;Is the fill pointer beyond the end?
  1247.     BLO.S    KBF20        ;Branch if not
  1248.     LEA    KEYSTRT-@-2(PC),A0 ;Wrap fill pointer back to beginning
  1249. KBF20    CMPA.L    KEYEMTY-@-2(PC),A0 ;Is the buffer full?
  1250.     BEQ.S    KBF30        ;Branch if it is -- don't increment ptr
  1251.     MOVE.L    A0,KEYFILL.L    ;Save fill pointer
  1252. KBF30
  1253.     RTS
  1254.  
  1255.  
  1256. END    EQU    @-1        ;Address where this handler ends
  1257.  
  1258.     IF    @ > MEMTOP - $180
  1259.     ERROR -- FILE IS TOO LONG (NEED ROOM FOR SYSTEM STACK)
  1260.     ELSE
  1261.     DCB.B    MEMTOP-@, 0    ;Fill the rest of the block with zeros
  1262.     ENDIF
  1263.  
  1264. ;----------------------------------------------------------------------
  1265. ;Hook these handlers into the device handler table as devices 0 and 1.
  1266. ;
  1267.     ORG    DEVTBL
  1268.     DC.L    CONHAN0
  1269.     DC.L    CONHAN1
  1270.  
  1271.     END
  1272. 
  1273. ;Hook these handlers into t